const parser = require('@babel/parser')
const traverse = require('@babel/traverse').default
const generate = require('@babel/generator').default

module.exports = function (source) {
  /************************** parse 解析阶段 **************************/

  /**
   * 调用 parser.parse(input, options) 根据源代码生成对应 AST
   * - input：源代码字符串
   */
  const ast = parser.parse(source, { sourceType: 'unambiguous' })

  /************************** transform 转换阶段 **************************/

  /**
   * 调用 traverse(parent, opts) 遍历各个节点，当命中指定类型节点时触发 callback
   * - parent：parser 生成的 AST
   */
  traverse(ast, {
    // 遍历到 debugger 关键字会调用该函数
    DebuggerStatement(path, state) {
      path.remove() // 移除该节点
    },
    // 遍历到调用表达式会调用该函数
    CallExpression(path, state) {
      // 1.获取 CallExpression 下的 callee 路径
      const calleePath = path.get('callee')
      // 2.检测 callee 路径是否部分匹配 console
      if (calleePath?.matchesPattern('console', true)) {
        // 2-1.获取当前路径父节点 ExpressionStatement 下的前缀注释
        const leadingComments = path.parentPath.node.leadingComments
        // 2-2.是否存在关键字注释
        let hasToken = false
        if (leadingComments?.length) {
          for (let i = 0; i < leadingComments.length; i++) {
            const commentNode = leadingComments[i]
            // 识别 行注释 和 块注释
            if (!['CommentLine', 'CommentBlock'].includes(commentNode.type)) {
              continue
            }
            // 是否存在关键字注释
            if (/\bunconsole-disable-next-line\b/g.test(commentNode.value)) {
              hasToken = true
              break
            }
          }
        }
        // 2-3.不存在关键字注释则移除该节点
        !hasToken && path.remove()
      }
    }
  })

  /************************** generate 生成阶段 **************************/

  /**
   * 调用 generate(ast) 根据 AST 生成对应目标代码
   */
  const { code } = generate(ast)

  return code
}
